/* file : engine.c */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <xaux_common.h>
#include <xaux_ext_common.h>
#include "unihan_xaux.h"
#include "unihan_property.h"

#include "engine.h"
#include "xaux_ext_status.h"

void
send_to_engine(int int_count, int *ints, int str_count, char **strs)
{
	int i;
	aux_ext_data_t *aux_data;

	if (im_ == VOID_IM_ID || ic_ == VOID_IC_ID || !xc_)
		return;

	if (!int_count && !str_count)
		return;

	aux_data = g_new0(aux_ext_data_t, 1);

	aux_data->im = im_;
	aux_data->ic = ic_;
	aux_data->integer_count = int_count;
	aux_data->string_count = str_count;

	if (aux_data->integer_count) {
		aux_data->integer_list = g_new0(int, aux_data->integer_count);
		for (i = 0; i < aux_data->integer_count; i++) {
			aux_data->integer_list[i] = ints[i];
		}
	}

	if (aux_data->string_count) {
		aux_data->string_list = g_new0(aux_ext_string_t, aux_data->string_count);
		for (i = 0; i < aux_data->string_count; i++) {
			aux_ext_string_t *p = &aux_data->string_list[i];
			p->length = strlen(strs[i]);
			p->ptr = (unsigned char *)strdup(strs[i]);
		}
	}

	gdk_error_trap_push();
	xaux_ext_SetValue(GDK_WINDOW_XDISPLAY(window->appletWindow->window), xc_, aux_data);
	if (gdk_error_trap_pop() != 0) {
		// BadWindow? we've lost xaux.so...
		im_ = VOID_IM_ID;
		ic_ = VOID_IC_ID;
		xc_ = NULL;
	}

	if (aux_data->integer_list)
		g_free(aux_data->integer_list);
	if (aux_data->string_list) {
		for (i = 0; i < aux_data->string_count; i++) {
			aux_ext_string_t *p = &aux_data->string_list[i];
			if (p && p->ptr)
				g_free(p->ptr);
		}
		g_free(aux_data->string_list);
	}
	g_free(aux_data);
}

void
send_props_to_engine(int num_props, UnihanPropertyArgList proplist)
{
	int int_values[21];
	char *str_values[21];
	int num_string;
	
	int_values[0] = UNIHAN_ENGINE_IM_SET_PROPS;
	str_values[0] = "null";
	
	num_string = convert_props_to_string(proplist, num_props, int_values, str_values);
#if DEBUG
	fprintf(stderr, "num_string:%d\n\r", num_string);
	//for(i = 1; i<num_string; i++)
	//	fprintf(stderr, "send to LE string_values[%d]:%s\n\r",i,str_values[i]);
#endif
	
	send_to_engine(num_string, int_values, num_string, str_values);
}

int
convert_props_to_string(UnihanPropertyArgList proplist,
		int num_props,
		int int_values[],
		char* string_values[])
{
	int num_string = 1;
	char *buf;
	int i;
	size_t size;
	
	while(proplist && num_props) {
		buf = (char*)malloc(sizeof(char)*50);
		memset(buf, 0, sizeof(char)*50);
		
		if(proplist->type == UNIHAN_RPOPERTY_USER) {
			int_values[num_string] = UNIHAN_RPOPERTY_USER;
			
			size = proplist->UnihanProperty.u_property.size;
			
			if(size > 100) {
				buf[0] = size / 100;
				buf[1] = size % 100;
			} else {
				buf[0] = 0;
				buf[1] = size;
			}
			if(size)
				memcpy(buf+2, proplist->UnihanProperty.u_property.priv_data, size);
			for(i = 0; i < size+2; i++) {
				if(buf[i] == 0)
					buf[i] = 127;
			}
			string_values[num_string] = buf;
			
		} else if(proplist->type == UNIHAN_PROPERTY_RUNTIME) {
			int_values[num_string] = UNIHAN_PROPERTY_RUNTIME;
			
			buf[0] = proplist->UnihanProperty.rt_property.rt_type+'0';
			buf[1] = proplist->UnihanProperty.rt_property.value+'0';
			
			if(proplist->UnihanProperty.rt_property.name.nr_name)
				buf[2] = proplist->UnihanProperty.rt_property.name.nr_name;
			else
				buf[2] = '0';
				
			if(proplist->UnihanProperty.rt_property.name.name_string)
				strcpy(buf+3, proplist->UnihanProperty.rt_property.name.name_string);
			else
				strcpy(buf+3, "null");
			strcat(buf,"|");
			
			if(proplist->UnihanProperty.rt_property.name.charset)
				strcat(buf, proplist->UnihanProperty.rt_property.name.charset);
			else
				strcat(buf, "null");
			strcat(buf,"|");

			if(proplist->UnihanProperty.rt_property.name.language)
				strcat(buf, proplist->UnihanProperty.rt_property.name.language);
			else
				strcat(buf, "null");
			strcat(buf,"|");
			
			if(proplist->UnihanProperty.rt_property.icon.icon0)
				strcat(buf, proplist->UnihanProperty.rt_property.icon.icon0);
			else
				strcat(buf, "null");
			strcat(buf,"|");

			if(proplist->UnihanProperty.rt_property.icon.icon1)
				strcat(buf, proplist->UnihanProperty.rt_property.icon.icon1);
			else
				strcat(buf, "null");
				 
			string_values[num_string] = buf;
		}
		num_string++;
		num_props--;
		proplist = proplist->next;
	}
	return num_string;	
}

int
convert_string_to_props(int int_values,
		unsigned char* string_values,
		UnihanPropertyArgList *pproplist)
{
	int i;
	size_t size;
	UnihanPropertyArgList new_property;
	
	if(string_values == NULL)
		return 0;
	
	new_property = (UnihanPropertyArgList)malloc(sizeof(UnihanPropertyArgs));
	
	if(int_values == UNIHAN_RPOPERTY_USER) {
		new_property->type = UNIHAN_RPOPERTY_USER;

		if(string_values[0] == 127)
			new_property->UnihanProperty.u_property.size =
					size =
					string_values[1];
		else
			new_property->UnihanProperty.u_property.size =
					size =
					string_values[0]*100 + string_values[1];
			
		for(i = 2; i<size+2; i++) {
			if(string_values[i] == 127)
				string_values[i] = 0;
		}
		new_property->UnihanProperty.u_property.priv_data = (void*)malloc(sizeof(char)*size);
		memcpy(new_property->UnihanProperty.u_property.priv_data, (void*)(string_values+2), size);
	} else if(int_values == UNIHAN_PROPERTY_RUNTIME) {
		char *p;
		char *delim = "|";

		new_property->type = UNIHAN_PROPERTY_RUNTIME;
		new_property->UnihanProperty.rt_property.rt_type = string_values[0]-'0';
		new_property->UnihanProperty.rt_property.value = string_values[1]-'0';
		if(string_values[2] == 127)
			new_property->UnihanProperty.rt_property.name.nr_name = 0;
		else
			new_property->UnihanProperty.rt_property.name.nr_name = string_values[2];
			
		p = strtok(string_values + 3, delim);
			
		if(strcmp(p,"null")!=0) {
			new_property->UnihanProperty.rt_property.name.name_string =
					(char*)malloc(sizeof(char)*(strlen(p)+1));
			strcpy(new_property->UnihanProperty.rt_property.name.name_string, p);
		} else {
			new_property->UnihanProperty.rt_property.name.name_string = NULL;
		}

		p = strtok(NULL , delim);

		if(strcmp(p,"null")!=0)
		{
			new_property->UnihanProperty.rt_property.name.charset =
					(char*)malloc(sizeof(char)*(strlen(p)+1));
			strcpy(new_property->UnihanProperty.rt_property.name.charset, p);
		} else {
			new_property->UnihanProperty.rt_property.name.charset = NULL;
		}
		
		p = strtok(NULL, delim);
		
		if(strcmp(p, "null") != 0) {
			new_property->UnihanProperty.rt_property.name.language =
					(char*)malloc(sizeof(char)*(strlen(p)+1));
			strcpy(new_property->UnihanProperty.rt_property.name.language, p);
		} else {
			new_property->UnihanProperty.rt_property.name.language = NULL;
		}
			 
		p = strtok(NULL, delim);
			
		if (strcmp(p, "null") != 0) {
			new_property->UnihanProperty.rt_property.icon.icon0 =
					(char*)malloc(sizeof(char)*(strlen(p)+1));
			strcpy(new_property->UnihanProperty.rt_property.icon.icon0, p);
		} else {
			new_property->UnihanProperty.rt_property.icon.icon0 = NULL;
		}
			
		p = strtok(NULL , delim);
			
		if (strcmp(p, "null") != 0) {
			new_property->UnihanProperty.rt_property.icon.icon1 =
					(char*)malloc(sizeof(char)*(strlen(p)+1));
			strcpy(new_property->UnihanProperty.rt_property.icon.icon1, p);
		}else{
			new_property->UnihanProperty.rt_property.icon.icon1 = NULL;
		}
	}

	if (*pproplist) {
		new_property->next = *pproplist;
	} else {
		new_property->next = NULL;
	}

	*pproplist = new_property;

	return 1;
}

void
destroy_im_property(UnihanPropertyArgList plist)
{
	UnihanPropertyArgList p;

	while(plist) {
		p = plist;
		plist = plist->next;
		if(p->type == UNIHAN_PROPERTY_RUNTIME) {
			if(p->UnihanProperty.rt_property.name.name_string)
				free(p->UnihanProperty.rt_property.name.name_string);

			if(p->UnihanProperty.rt_property.name.charset)
				free(p->UnihanProperty.rt_property.name.charset);

			if(p->UnihanProperty.rt_property.name.language)
				free(p->UnihanProperty.rt_property.name.language);

			if(p->UnihanProperty.rt_property.icon.icon0)
				free(p->UnihanProperty.rt_property.icon.icon0);

			if(p->UnihanProperty.rt_property.icon.icon1)
				free(p->UnihanProperty.rt_property.icon.icon1);
		} else if(p->type == UNIHAN_RPOPERTY_USER) {
			free(p->UnihanProperty.u_property.priv_data);
		}

		free(p);
	}
}
